
//**************************************************************************
//**
//** p_things.c : Heretic 2 : Raven Software, Corp.
//**
//** $Revision: 373 $
//** $Date: 2009-05-19 21:14:28 +0300 (Tue, 19 May 2009) $
//**
//**************************************************************************

// HEADER FILES ------------------------------------------------------------

#include "h2stdinc.h"
#include "h2def.h"
#include "p_local.h"
#include "soundst.h"

// MACROS ------------------------------------------------------------------

// TYPES -------------------------------------------------------------------

// EXTERNAL FUNCTION PROTOTYPES --------------------------------------------

// PUBLIC FUNCTION PROTOTYPES ----------------------------------------------

// PRIVATE FUNCTION PROTOTYPES ---------------------------------------------

static BOOLEAN ActivateThing(mobj_t *mobj);
static BOOLEAN DeactivateThing(mobj_t *mobj);

// EXTERNAL DATA DECLARATIONS ----------------------------------------------

// PUBLIC DATA DEFINITIONS -------------------------------------------------

mobjtype_t TranslateThingType[] =
{
	MT_MAPSPOT,		/* T_NONE		*/
	MT_CENTAUR,		/* T_CENTAUR		*/
	MT_CENTAURLEADER,	/* T_CENTAURLEADER	*/
	MT_DEMON,		/* T_DEMON		*/
	MT_ETTIN,		/* T_ETTIN		*/
	MT_FIREDEMON,		/* T_FIREGARGOYLE	*/
	MT_SERPENT,		/* T_WATERLURKER	*/
	MT_SERPENTLEADER,	/* T_WATERLURKERLEADER	*/
	MT_WRAITH,		/* T_WRAITH		*/
	MT_WRAITHB,		/* T_WRAITHBURIED	*/
	MT_FIREBALL1,		/* T_FIREBALL1		*/
	MT_MANA1,		/* T_MANA1		*/
	MT_MANA2,		/* T_MANA2		*/
	MT_SPEEDBOOTS,		/* T_ITEMBOOTS		*/
	MT_ARTIEGG,		/* T_ITEMEGG		*/
	MT_ARTIFLY,		/* T_ITEMFLIGHT		*/
	MT_SUMMONMAULATOR,	/* T_ITEMSUMMON		*/
	MT_TELEPORTOTHER,	/* T_ITEMTPORTOTHER	*/
	MT_ARTITELEPORT,	/* T_ITEMTELEPORT	*/
	MT_BISHOP,		/* T_BISHOP		*/
	MT_ICEGUY,		/* T_ICEGOLEM		*/
	MT_BRIDGE,		/* T_BRIDGE		*/
	MT_BOOSTARMOR,		/* T_DRAGONSKINBRACERS	*/
	MT_HEALINGBOTTLE,	/* T_ITEMHEALTHPOTION	*/
	MT_HEALTHFLASK,		/* T_ITEMHEALTHFLASK	*/
	MT_ARTISUPERHEAL,	/* T_ITEMHEALTHFULL	*/
	MT_BOOSTMANA,		/* T_ITEMBOOSTMANA	*/
	MT_FW_AXE,		/* T_FIGHTERAXE		*/
	MT_FW_HAMMER,		/* T_FIGHTERHAMMER	*/
	MT_FW_SWORD1,		/* T_FIGHTERSWORD1	*/
	MT_FW_SWORD2,		/* T_FIGHTERSWORD2	*/
	MT_FW_SWORD3,		/* T_FIGHTERSWORD3	*/
	MT_CW_SERPSTAFF,	/* T_CLERICSTAFF	*/
	MT_CW_HOLY1,		/* T_CLERICHOLY1	*/
	MT_CW_HOLY2,		/* T_CLERICHOLY2	*/
	MT_CW_HOLY3,		/* T_CLERICHOLY3	*/
	MT_MW_CONE,		/* T_MAGESHARDS		*/
	MT_MW_STAFF1,		/* T_MAGESTAFF1		*/
	MT_MW_STAFF2,		/* T_MAGESTAFF2		*/
	MT_MW_STAFF3,		/* T_MAGESTAFF3		*/
	MT_EGGFX,		/* T_MORPHBLAST		*/
	MT_ROCK1,		/* T_ROCK1		*/
	MT_ROCK2,		/* T_ROCK2		*/
	MT_ROCK3,		/* T_ROCK3		*/
	MT_DIRT1,		/* T_DIRT1		*/
	MT_DIRT2,		/* T_DIRT2		*/
	MT_DIRT3,		/* T_DIRT3		*/
	MT_DIRT4,		/* T_DIRT4		*/
	MT_DIRT5,		/* T_DIRT5		*/
	MT_DIRT6,		/* T_DIRT6		*/
	MT_ARROW,		/* T_ARROW		*/
	MT_DART,		/* T_DART		*/
	MT_POISONDART,		/* T_POISONDART		*/
	MT_RIPPERBALL,		/* T_RIPPERBALL		*/
	MT_SGSHARD1,		/* T_STAINEDGLASS1	*/
	MT_SGSHARD2,		/* T_STAINEDGLASS2	*/
	MT_SGSHARD3,		/* T_STAINEDGLASS3	*/
	MT_SGSHARD4,		/* T_STAINEDGLASS4	*/
	MT_SGSHARD5,		/* T_STAINEDGLASS5	*/
	MT_SGSHARD6,		/* T_STAINEDGLASS6	*/
	MT_SGSHARD7,		/* T_STAINEDGLASS7	*/
	MT_SGSHARD8,		/* T_STAINEDGLASS8	*/
	MT_SGSHARD9,		/* T_STAINEDGLASS9	*/
	MT_SGSHARD0,		/* T_STAINEDGLASS0	*/
	MT_PROJECTILE_BLADE,	/* T_BLADE		*/
	MT_ICESHARD,		/* T_ICESHARD		*/
	MT_FLAME_SMALL,		/* T_FLAME_SMALL	*/
	MT_FLAME_LARGE,		/* T_FLAME_LARGE	*/
	MT_ARMOR_1,		/* T_MESHARMOR		*/
	MT_ARMOR_2,		/* T_FALCONSHIELD	*/
	MT_ARMOR_3,		/* T_PLATINUMHELM	*/
	MT_ARMOR_4,		/* T_AMULETOFWARDING	*/
	MT_ARTIPOISONBAG,	/* T_ITEMFLECHETTE	*/
	MT_ARTITORCH,		/* T_ITEMTORCH		*/
	MT_BLASTRADIUS,		/* T_ITEMREPULSION	*/
	MT_MANA3,		/* T_MANA3		*/
	MT_ARTIPUZZSKULL,	/* T_PUZZSKULL		*/
	MT_ARTIPUZZGEMBIG,	/* T_PUZZGEMBIG		*/
	MT_ARTIPUZZGEMRED,	/* T_PUZZGEMRED		*/
	MT_ARTIPUZZGEMGREEN1,	/* T_PUZZGEMGREEN1	*/
	MT_ARTIPUZZGEMGREEN2,	/* T_PUZZGEMGREEN2	*/
	MT_ARTIPUZZGEMBLUE1,	/* T_PUZZGEMBLUE1	*/
	MT_ARTIPUZZGEMBLUE2,	/* T_PUZZGEMBLUE2	*/
	MT_ARTIPUZZBOOK1,	/* T_PUZZBOOK1		*/
	MT_ARTIPUZZBOOK2,	/* T_PUZZBOOK2		*/
	MT_KEY1,		/* T_METALKEY		*/
	MT_KEY2,		/* T_SMALLMETALKEY	*/
	MT_KEY3,		/* T_AXEKEY		*/
	MT_KEY4,		/* T_FIREKEY		*/
	MT_KEY5,		/* T_GREENKEY		*/
	MT_KEY6,		/* T_MACEKEY		*/
	MT_KEY7,		/* T_SILVERKEY		*/
	MT_KEY8,		/* T_RUSTYKEY		*/
	MT_KEY9,		/* T_HORNKEY		*/
	MT_KEYA,		/* T_SERPENTKEY		*/
	MT_WATER_DRIP,		/* T_WATERDRIP		*/
	MT_FLAME_SMALL_TEMP,	/* T_TEMPSMALLFLAME	*/
	MT_FLAME_SMALL,		/* T_PERMSMALLFLAME	*/
	MT_FLAME_LARGE_TEMP,	/* T_TEMPLARGEFLAME	*/
	MT_FLAME_LARGE,		/* T_PERMLARGEFLAME	*/
	MT_DEMON_MASH,		/* T_DEMON_MASH		*/
	MT_DEMON2_MASH,		/* T_DEMON2_MASH	*/
	MT_ETTIN_MASH,		/* T_ETTIN_MASH		*/
	MT_CENTAUR_MASH,	/* T_CENTAUR_MASH	*/
	MT_THRUSTFLOOR_UP,	/* T_THRUSTSPIKEUP	*/
	MT_THRUSTFLOOR_DOWN,	/* T_THRUSTSPIKEDOWN	*/
	MT_WRAITHFX4,		/* T_FLESH_DRIP1	*/
	MT_WRAITHFX5,		/* T_FLESH_DRIP2	*/
	MT_WRAITHFX2		/* T_SPARK_DRIP		*/
};

// PRIVATE DATA DEFINITIONS ------------------------------------------------

// CODE --------------------------------------------------------------------

//==========================================================================
//
// EV_ThingProjectile
//
//==========================================================================

BOOLEAN EV_ThingProjectile(byte *args, BOOLEAN gravity)
{
	int tid;
	angle_t angle;
	int fineAngle;
	fixed_t speed;
	fixed_t vspeed;
	mobjtype_t moType;
	mobj_t *mobj;
	mobj_t *newMobj;
	int searcher;
	BOOLEAN success;

	success = false;
	searcher = -1;
	tid = args[0];
	moType = TranslateThingType[args[1]];
	if (nomonsters && (mobjinfo[moType].flags & MF_COUNTKILL))
	{ // Don't spawn monsters if -nomonsters
		return false;
	}
	angle = (int)args[2]<<24;
	fineAngle = angle>>ANGLETOFINESHIFT;
	speed = (int)args[3]<<13;
	vspeed = (int)args[4]<<13;
	while ((mobj = P_FindMobjFromTID(tid, &searcher)) != NULL)
	{
		newMobj = P_SpawnMobj(mobj->x, mobj->y, mobj->z, moType);
		if (newMobj->info->seesound)
		{
			S_StartSound(newMobj, newMobj->info->seesound);
		}
		newMobj->target = mobj; // Originator
		newMobj->angle = angle;
		newMobj->momx = FixedMul(speed, finecosine[fineAngle]);
		newMobj->momy = FixedMul(speed, finesine[fineAngle]);
		newMobj->momz = vspeed;
		newMobj->flags2 |= MF2_DROPPED; // Don't respawn
		if (gravity == true)
		{
			newMobj->flags &= ~MF_NOGRAVITY;
			newMobj->flags2 |= MF2_LOGRAV;
		}
		if (P_CheckMissileSpawn(newMobj) == true)
		{
			success = true;
		}
	}
	return success;
}

//==========================================================================
//
// EV_ThingSpawn
//
//==========================================================================

BOOLEAN EV_ThingSpawn(byte *args, BOOLEAN fog)
{
	int tid;
	angle_t angle;
	mobj_t *mobj;
	mobj_t *newMobj;
	mobj_t *fogMobj;
	mobjtype_t moType;
	int searcher;
	BOOLEAN success;
	fixed_t z;

	success = false;
	searcher = -1;
	tid = args[0];
	moType = TranslateThingType[args[1]];
	if (nomonsters && (mobjinfo[moType].flags & MF_COUNTKILL))
	{ // Don't spawn monsters if -nomonsters
		return false;
	}
	angle = (int)args[2]<<24;
	while ((mobj = P_FindMobjFromTID(tid, &searcher)) != NULL)
	{
		if (mobjinfo[moType].flags2 & MF2_FLOATBOB)
		{
			z = mobj->z - mobj->floorz;
		}
		else
		{
			z = mobj->z;
		}
		newMobj = P_SpawnMobj(mobj->x, mobj->y, z, moType);
		if (P_TestMobjLocation(newMobj) == false)
		{ // Didn't fit
			P_RemoveMobj(newMobj);
		}
		else
		{
			newMobj->angle = angle;
			if (fog == true)
			{
				fogMobj = P_SpawnMobj(mobj->x, mobj->y, mobj->z + TELEFOGHEIGHT, MT_TFOG);
				S_StartSound(fogMobj, SFX_TELEPORT);
			}
			newMobj->flags2 |= MF2_DROPPED; // Don't respawn
			if (newMobj->flags2 & MF2_FLOATBOB)
			{
				newMobj->special1 = newMobj->z - newMobj->floorz;
			}
			success = true;
		}
	}
	return success;
}

//==========================================================================
//
// EV_ThingActivate
//
//==========================================================================

BOOLEAN EV_ThingActivate(int tid)
{
	mobj_t *mobj;
	int searcher;
	BOOLEAN success;

	success = false;
	searcher = -1;
	while ((mobj = P_FindMobjFromTID(tid, &searcher)) != NULL)
	{
		if (ActivateThing(mobj) == true)
		{
			success = true;
		}
	}
	return success;
}

//==========================================================================
//
// EV_ThingDeactivate
//
//==========================================================================

BOOLEAN EV_ThingDeactivate(int tid)
{
	mobj_t *mobj;
	int searcher;
	BOOLEAN success;

	success = false;
	searcher = -1;
	while ((mobj = P_FindMobjFromTID(tid, &searcher)) != NULL)
	{
		if (DeactivateThing(mobj) == true)
		{
			success = true;
		}
	}
	return success;
}

//==========================================================================
//
// EV_ThingRemove
//
//==========================================================================

BOOLEAN EV_ThingRemove(int tid)
{
	mobj_t *mobj;
	int searcher;
	BOOLEAN success;

	success = false;
	searcher = -1;
	while ((mobj = P_FindMobjFromTID(tid, &searcher)) != NULL)
	{
		if (mobj->type == MT_BRIDGE)
		{
			A_BridgeRemove(mobj);
			return true;
		}
		P_RemoveMobj(mobj);
		success = true;
	}
	return success;
}

//==========================================================================
//
// EV_ThingDestroy
//
//==========================================================================

BOOLEAN EV_ThingDestroy(int tid)
{
	mobj_t *mobj;
	int searcher;
	BOOLEAN success;

	success = false;
	searcher = -1;
	while ((mobj = P_FindMobjFromTID(tid, &searcher)) != NULL)
	{
		if (mobj->flags & MF_SHOOTABLE)
		{
			P_DamageMobj(mobj, NULL, NULL, 10000);
			success = true;
		}
	}
	return success;
}

//==========================================================================
//
// EV_ThingMove
//
// arg[0] = tid
// arg[1] = speed
// arg[2] = angle (255 = use mobj angle)
// arg[3] = distance (pixels>>2)
//
//==========================================================================

/*
BOOLEAN EV_ThingMove(byte *args)
{
	return false;
}
*/

//==========================================================================
//
// ActivateThing
//
//==========================================================================

static BOOLEAN ActivateThing(mobj_t *mobj)
{
	if (mobj->flags & MF_COUNTKILL)
	{ // Monster
		if (mobj->flags2 & MF2_DORMANT)
		{
			mobj->flags2 &= ~MF2_DORMANT;
			mobj->tics = 1;
			return true;
		}
		return false;
	}
	switch (mobj->type)
	{
	case MT_ZTWINEDTORCH:
	case MT_ZTWINEDTORCH_UNLIT:
		P_SetMobjState(mobj, S_ZTWINEDTORCH_1);
		S_StartSound(mobj, SFX_IGNITE);
		break;
	case MT_ZWALLTORCH:
	case MT_ZWALLTORCH_UNLIT:
		P_SetMobjState(mobj, S_ZWALLTORCH1);
		S_StartSound(mobj, SFX_IGNITE);
		break;
	case MT_ZGEMPEDESTAL:
		P_SetMobjState(mobj, S_ZGEMPEDESTAL2);
		break;
	case MT_ZWINGEDSTATUENOSKULL:
		P_SetMobjState(mobj, S_ZWINGEDSTATUENOSKULL2);
		break;
	case MT_THRUSTFLOOR_UP:
	case MT_THRUSTFLOOR_DOWN:
		if (mobj->args[0] == 0)
		{
			S_StartSound(mobj, SFX_THRUSTSPIKE_LOWER);
			mobj->flags2 &= ~MF2_DONTDRAW;
			if (mobj->args[1])
				P_SetMobjState(mobj, S_BTHRUSTRAISE1);
			else
				P_SetMobjState(mobj, S_THRUSTRAISE1);
		}
		break;
	case MT_ZFIREBULL:
	case MT_ZFIREBULL_UNLIT:
		P_SetMobjState(mobj, S_ZFIREBULL_BIRTH);
		S_StartSound(mobj, SFX_IGNITE);
		break;
	case MT_ZBELL:
		if (mobj->health > 0)
		{
			P_DamageMobj(mobj, NULL, NULL, 10); // 'ring' the bell
		}
		break;
	case MT_ZCAULDRON:
	case MT_ZCAULDRON_UNLIT:
		P_SetMobjState(mobj, S_ZCAULDRON1);
		S_StartSound(mobj, SFX_IGNITE);
		break;
	case MT_FLAME_SMALL:
		S_StartSound(mobj, SFX_IGNITE);
		P_SetMobjState(mobj, S_FLAME_SMALL1);
		break;
	case MT_FLAME_LARGE:
		S_StartSound(mobj, SFX_IGNITE);
		P_SetMobjState(mobj, S_FLAME_LARGE1);
		break;
	case MT_BAT_SPAWNER:
		P_SetMobjState(mobj, S_SPAWNBATS1);
		break;
	default:
		return false;
	}
	return true;
}

//==========================================================================
//
// DeactivateThing
//
//==========================================================================

static BOOLEAN DeactivateThing(mobj_t *mobj)
{
	if (mobj->flags & MF_COUNTKILL)
	{ // Monster
		if (!(mobj->flags2 & MF2_DORMANT))
		{
			mobj->flags2 |= MF2_DORMANT;
			mobj->tics = -1;
			return true;
		}
		return false;
	}
	switch (mobj->type)
	{
	case MT_ZTWINEDTORCH:
	case MT_ZTWINEDTORCH_UNLIT:
		P_SetMobjState(mobj, S_ZTWINEDTORCH_UNLIT);
		break;
	case MT_ZWALLTORCH:
	case MT_ZWALLTORCH_UNLIT:
		P_SetMobjState(mobj, S_ZWALLTORCH_U);
		break;
	case MT_THRUSTFLOOR_UP:
	case MT_THRUSTFLOOR_DOWN:
		if (mobj->args[0] == 1)
		{
			S_StartSound(mobj, SFX_THRUSTSPIKE_RAISE);
			if (mobj->args[1])
				P_SetMobjState(mobj, S_BTHRUSTLOWER);
			else
				P_SetMobjState(mobj, S_THRUSTLOWER);
		}
		break;
	case MT_ZFIREBULL:
	case MT_ZFIREBULL_UNLIT:
		P_SetMobjState(mobj, S_ZFIREBULL_DEATH);
		break;
	case MT_ZCAULDRON:
	case MT_ZCAULDRON_UNLIT:
		P_SetMobjState(mobj, S_ZCAULDRON_U);
		break;
	case MT_FLAME_SMALL:
		P_SetMobjState(mobj, S_FLAME_SDORM1);
		break;
	case MT_FLAME_LARGE:
		P_SetMobjState(mobj, S_FLAME_LDORM1);
		break;
	case MT_BAT_SPAWNER:
		P_SetMobjState(mobj, S_SPAWNBATS_OFF);
		break;
	default:
		return false;
	}
	return true;
}

